home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
misc
/
emu
/
Apex-src.lha
/
INT.68K
< prev
next >
Wrap
Text File
|
2001-09-30
|
34KB
|
1,232 lines
;INT.68K MAR-20-87
;XPL intrinsics for the 68000
;Written by Loren Blaney
;This is derived from 6502 code written by P.J.R. Boyle.
;
;REVISION HISTORY:
;DEC-84, Original, known as: INT.68K.
;DEC-85, Added floating point intrinsics.
;FEB-86, Modified for 32-bit operations for DFM engineering.
;MAR-86, Modified for double-precision floating point.
;SEP-86, Converted to ASM68K conventions and modified.
;OCT-86, Modified to run in supervisor mode and to interface cleanly
; with assembly language.
;NOV-86, Modified for second terminal (device 1)
;DEC-86, Added OPENF intrinsic and removed FASAVE
;FEB-87, Fixed test for file too long.
;MAR-87, Fixed remainder.
;
;Notes:
;These intrinsics may destroy the contents of registers D0 and A6;
; however, subroutines should not destroy the contents of registers. If,
; in the interest of speed, registers are not saved and restored, this
; should be clearly stated as part of the operation of the subroutine.
;
NOLIST
INCLUDE SYSPAG ;Get system page definitions
LIST
;-----------------------------------------------------------------------
;INTRINSIC JUMP TABLE
;
ORG INTTBL ;Compiler expects the jump table here
JMP ABS.L ;0
JMP RAN.L ;1
JMP REM.L ;2
JMP RESERV.L ;3
JMP SWAP.L ;4
JMP EXTEND.L ;5
JMP RESTAR.L ;6
JMP CHIN.L ;7
JMP CHOUT.L ;8
JMP CRLF.L ;9
JMP INTIN.L ;10
JMP INTOUT.L ;11
JMP TEXT.L ;12
JMP OPENI.L ;13
JMP OPENO.L ;14
JMP CLOSE.L ;15
JMP ABORT.L ;16
JMP BADINT.L ;TRAP.L ;17
JMP FREE.L ;18
JMP RERUN.L ;19
JMP GETHP.L ;20
JMP SETHP.L ;21
JMP BADINT.L ;GETERR.L ;22
JMP CURSOR.L ;23
JMP SCAN.L ;24
JMP SETRUN.L ;25
JMP HEXIN.L ;26
JMP HEXOUT.L ;27
JMP CHAIN.L ;28
JMP OPENF.L ;29
JMP WRITE.L ;30
JMP READ.L ;31
JMP BADINT.L ;TESTPT.L ;32
;Special intrinsics for Apex:
JMP FGET.L ;33
JMP BADINT.L ;FASAVE.L ;34
JMP FSAVE.L ;35
JMP BLIT.L ;36
; JMP BADINT.L ;SETTXT.L ;33
; JMP BADINT.L ;SETHI.L ;34
; JMP BADINT.L ;SETMIX.L ;35
; JMP BADINT.L ;SETLO.L ;36
JMP BADINT.L ;BUTTON.L ;37
JMP BADINT.L ;PADDLE.L ;38
JMP BADINT.L ;SOUND.L ;39
JMP BADINT.L ;CLEAR.L ;40
JMP BADINT.L ;POINT.L ;41
JMP BADINT.L ;LINE.L ;42
JMP BADINT.L ;MOVE.L ;43
JMP BADINT.L ;SCREEN.L ;44
JMP BADINT.L ;BLOCK.L ;45
JMP RLRES.L ;46
JMP RLIN.L ;47
JMP RLOUT.L ;48
JMP FLOAT.L ;49
JMP FIX.L ;50
JMP RLABS.L ;51
JMP FORMAT.L ;52
JMP SQRT.L ;53
JMP LN.L ;54
JMP EXP.L ;55
JMP SIN.L ;56
JMP ATAN2.L ;57
JMP MOD.L ;58
JMP LOG.L ;59
JMP COS.L ;60
JMP TAN.L ;61
JMP ASIN.L ;62
JMP ACOS.L ;63
JMP BACKUP.L ;64
JMP BADINT.L ;HICHAR.L ;65
JMP BADINT.L ;PEEK.L ;66
JMP BADINT.L ;POKE.L ;67
JMP BADINT.L ;68
JMP BADINT.L ;69
JMP BADINT.L ;70
JMP BADINT.L ;71
JMP BADINT.L ;72
JMP BADINT.L ;73
JMP BADINT.L ;74
JMP BADINT.L ;75
JMP BADINT.L ;76
JMP BADINT.L ;77
JMP BADINT.L ;78
JMP BADINT.L ;79
JMP BADINT.L ;80
JMP BADINT.L ;81
JMP BADINT.L ;82
JMP BADINT.L ;83
JMP BADINT.L ;84
JMP BADINT.L ;85
JMP BADINT.L ;86
JMP BADINT.L ;87
JMP BADINT.L ;88
JMP BADINT.L ;89
JMP BADINT.L ;90
JMP BADINT.L ;91
JMP BADINT.L ;92
JMP BADINT.L ;93
JMP BADINT.L ;94
JMP BADINT.L ;95
JMP BADINT.L ;96
JMP BADINT.L ;97
JMP BADINT.L ;98
JMP BADINT.L ;99
JMP BADINT.L ;100
JMP BADINT.L ;101
JMP BADINT.L ;102
JMP BADINT.L ;103
JMP BADINT.L ;104
JMP BADINT.L ;105
JMP BADINT.L ;106
JMP BADINT.L ;107
JMP BADINT.L ;108
JMP BADINT.L ;109
JMP BADINT.L ;110
JMP BADINT.L ;111
JMP BADINT.L ;112
JMP BADINT.L ;113
JMP BADINT.L ;114
JMP BADINT.L ;115
JMP BADINT.L ;116
JMP BADINT.L ;117
JMP BADINT.L ;118
JMP CURSOR1.L ;119
JMP BUTES1.L ;120
JMP SHOCUR1.L ;121
JMP DEVINFO.L ;122
JMP UNTINFO.L ;123
JMP BUTES.L ;124
JMP GETKEY.L ;125
JMP KEYHIT.L ;126
JMP SHOCUR.L ;127
;-----------------------------------------------------------------------
;All INT.68K variables are stored here. The compiler must know the
; location of REMAIN. The rest are grouped here for convenience when
; they are saved and restored by the multitasking exec.
;
REMAIN DS.L 1 ;Remainder of most recent divide
RANK DC.L 2537 ;Random number seeds (initialized at
RANL DC.L 5149 ; load time)
RANM DC.L 7026 ;Random number that is actually output
BACKFL DS.B 1 ;Backup flag, used to re-read last char
LASTCH DS.B 1 ;The last character read by BYTEIN
;-----------------------------------------------------------------------
;
ORG MEMTOP -$3800
;
;Illegal intrinsic handler. (Note: this would be improved a tremendous
; amount if it said where it came from.)
;
BADINT JSR VERROR
ASCII '105 - ILLEGAL INTRINSI'
DC.B 'C'+$80
RTS
;-----------------------------------------------------------------------
;0
;Return the absolute value of the argument in D0.
; I:= ABS(J)
;
ABS MOVE.L (A5),D0
BPL.S ABS10
NEG.L D0
ABS10 RTS
;-----------------------------------------------------------------------
;1
;Return a random number, between 0 and the argument-1, in D0.
; If the argument = 0, then the seeds are reinitialized (for a
; repeatable sequence). If the argument < 0 then randomize and
; return a positive value between 0 and -(argument-1).
; I:= RAN(10)
; *** THIS IS CURRENTLY A 16-BIT OPERATION ***
;
RAN TST.L (A5) ;Is the argument = 0
BNE.S RANF10 ;Branch if not
BSR.S RANINI ;Initialize seeds
MOVEQ #0,D0 ;Return 0
BRA.S RANF90
RANF10 BPL.S RANF20 ;Branch if the argument is positive
MOVE.L HASH,RANM ;Randomize with keyboard spinner
NEG.L (A5) ;Return a positive random number
RANF20 BSR.S RANDOM ;Get a random number
DIVS 2(A5),D0 ;D0:= REM(D0 / 2(A5))
CLR.W D0 ;Clear quotient
SWAP D0 ;Get remainder into low word
RANF90 RTS
;
;Initialize the random number seeds
;
RANINI MOVE.L #2537,RANK ;Reinitialize the seeds
MOVE.L #5149,RANL
MOVE.L #7026,RANM
RTS
;
;Return a random number, between 0 and 10860, in D0.
;*** should be increased to 32 bit values *** ????
;
MODK EQU 10909 ;Modulo values (prime numbers)
MODL EQU 10891
MODM EQU 10861
RANDOM MOVE.L RANK,D0 ;RANK:=2*RANK modulo MODK
ADD.L D0,D0
CMP.L #MODK,D0
BLT.S RAN10
SUB.L #MODK,D0
RAN10 MOVE.L D0,RANK
MOVE.L RANL,D0 ;RANL:=2*RANL modulo MODL
ADD.L D0,D0
CMP.L #MODL,D0
BLT.S RAN20
SUB.L #MODL,D0
RAN20 MOVE.L D0,RANL
ADD.L RANK,D0 ;RANM:= (RANK+RANL+RANM) modulo MODM
ADD.L RANM,D0
RAN30 CMP.L #MODM,D0
BLT.S RAN99
SUB.L #MODM,D0
BRA.S RAN30
RAN99 MOVE.L D0,RANM
RTS
;-----------------------------------------------------------------------
;2
;Return the remainder of the last integer divide in D0.
; The sign of the remainder is always the same as the dividend unless the
; remainder is equal to zero.
; I:= REM(5/3)
;
REM MOVE.W REMAIN,D0 ;Get high word (the actual 16-bit
EXT.L D0 ; remainder). Extend to 32-bits
RTS
;-----------------------------------------------------------------------
;3
;Reserve heap space for an array (A5:= A5 + <ARG>).
; ADDR:= RESERVE(BYTES)
; The starting (low) address of the reserved space in returned in D0.
;WARNING: This assumes that the heap and the stack are arranged so that
; they grow toward each other.
;
RESERV MOVE.L A5,D0 ;Return the base address in D0
BTST #0,3(A5) ;Make sure he is reserving an even
BEQ.S RES10 ; number of bytes, branch if so
ADDQ.B #1,3(A5) ;Add one more byte to make it even
RES10
ADDA.L (A5),A5 ;Add the argument number of bytes
; to the heap pointer (A5)
CMPA.L SP,A5 ;Check for memory overflow
BLO.S RES90
JSR VERROR
ASCII '102 - MEMORY OVERFLO'
DC.B 'W'+$80
RES90 RTS
;-----------------------------------------------------------------------
;4
;Swap bytes in a word.
; The swapped bytes of the argument are returned in D0.
; I:= SWAP($3412)
;
SWAP MOVE.L (A5),D0
ROL.W #8,D0
RTS
;-----------------------------------------------------------------------
;5
;Extend the sign bit of a byte to 32 bits (a word).
; The sign-extended argument is returned in D0.
; I:= EXTEND($80)
;
EXTEND MOVE.B 3(A5),D0
EXT.W D0
EXT.L D0
RTS
;-----------------------------------------------------------------------
;6
;Restart the current (XPL) program.
; RESTART
;
RESTAR ST RERUNF ;Set the RERUN flag
CLR.L ERRLOC ;Indicate no errors
MOVEA.L STACK,SP ;Set the stack pointer
MOVEA.L HEAP,A5 ;Set the heap pointer
JSR VRSTRT ;Call the current program
JSR VSHOERR ;Display any errors
JMP VEXIT ;Take the program's exit vector
;-----------------------------------------------------------------------
;7
;Return a byte from input device DEV in D0.
; BYTE:= CHIN(DEV);
;
CHIN MOVE.B 3(A5),DEVICE ;Get the device number
BRA BYTEIN ;(PBRA) returns with byte in D0
;-----------------------------------------------------------------------
;8
;Send a byte to device DEV.
; CHOUT(DEV,BYTE);
; A6 and D0 are destroyed.
;
CHOUT MOVE.B 3(A5),DEVICE ;Get the device number
MOVE.B 7(A5),D0 ;Get the character
MOVEA.W #12,A6 ;Set the function code = CHOUT
JMP VDEVHAN ;(PJMP) output D0
;-----------------------------------------------------------------------
;9
;Send a "new line" command to DEV
; CRLF(DEV)
; A6 and D0 are destroyed.
;
CRLF MOVE.B 3(A5),DEVICE ;Get the device number
MOVEQ #CR,D0 ;CR = new line (LF is not used)
MOVEA.W #12,A6 ;Set the function code = CHOUT
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;10
;Get a signed, decimal ASCII string from device DEV, convert it to a
; binary long word, and return it in D0.
; I:= INTIN(DEV)
;
INTIN MOVE.B 3(A5),DEVICE ;Get the device number
BRA INTI ;(PBRA) return the integer in D0
;-----------------------------------------------------------------------
;11
;Convert a 32-bit integer to a signed, decimal ASCII string and send it
; out to device DEV.
; INTOUT(DEV,I)
; D0 is destroyed.
;
INTOUT MOVE.B 3(A5),DEVICE ;Get the device number
MOVE.L 4(A5),D0 ;Get the integer
BRA INTO ;(PBRA) output the integer
;-----------------------------------------------------------------------
;12
;Output the ASCII string at address ADDR to I/O device DEV.
; TEXT(DEV,ADDR)
; A6 is destroyed.
;
TEXT MOVE.B 3(A5),DEVICE ;Get the device number
MOVEA.L 4(A5),A6 ;Get the address
BRA TEXTO ;(PBRA) output the string
;-----------------------------------------------------------------------
;13
;Open (initialize) a device for input.
; OPENI(DEV)
; A6 is destroyed.
;
OPENI MOVE.B 3(A5),DEVICE ;Get the device number
MOVEA.W #0,A6 ;Set the function code = OPENI
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;14
;Open (initialize) a device for output.
; OPENO(DEV)
; A6 is destroyed.
;
OPENO MOVE.B 3(A5),DEVICE ;Get the device number
MOVEA.W #4,A6 ;Set the function code = OPENO
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;15
;Close an output device (flushes buffers, etc.)
; CLOSE(DEV)
; A6 is destroyed.
;
CLOSE MOVE.B 3(A5),DEVICE ;Get the device number
MOVEA.W #16,A6 ;Set the function code = CLOSE
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;16
;Abort the XPL program (same as a CTRL-P exit)
; ABORT
;
ABORT JMP VABORT
;-----------------------------------------------------------------------
;17
TRAP RTS
;-----------------------------------------------------------------------
;18
;Return the amount of free space left in the heap and the stack.
; WARNING: It is assumed here that the stack and the heap are set up
; such that they grow toward each other.
; I := FREE
;
FREE MOVE.L SP,D0 ;RETURN (SP - A5)
SUB.L A5,D0
RTS
;-----------------------------------------------------------------------
;19
;Return the rerun flag
; FLAG := RERUN
;
RERUN MOVE.B RERUNF,D0
EXT.W D0
EXT.L D0
RTS
;-----------------------------------------------------------------------
;20
;Return the heap pointer
; ADDR := GETHP
;
GETHP MOVE.L A5,D0
RTS
;-----------------------------------------------------------------------
;21
;Set the heap pointer.
; SETHP($2000)
; (The user had better have a good idea of the functioning of XPL before
; dinging with the heap pointer or he will surely bomb himself!)
; A6 is destroyed.
;
SETHP MOVEA.L (A5),A5
RTS
;-----------------------------------------------------------------------
;22
; I:= GETERR;
GETERR
RTS
;-----------------------------------------------------------------------
;23
;Move cursor of device 0 to column X, line Y. Upper left corner is
; X,Y = 0,0.
; CURSOR(X,Y)
; A6 is destroyed.
;
CURSOR MOVE.B #0,DEVICE ;Set to device number 0
MOVE.B 3(A5),D0 ;Get X position
ROL.W #8,D0 ;Put it into high byte of D0
MOVE.B 7(A5),D0 ;Get Y position into low byte
MOVEA.W #28,A6 ;Set function code = "position cursor"
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;24
;Scan the directory for a file name and return its start and end blocks
; SCAN(UNIT, INFO, NAME)
; UNIT - unit number (0-7)
; INFO - the address of a 2-integer array where the starting and
; ending blocks are returned
; NAME - the address of a 12-byte file name
; (note: the 11th byte cannot have its MSB set)
;
SCAN MOVE.B 3(A5),UNIT ;Get the unit argument
MOVEA.L 8(A5),A6 ;Point A6 to the file name
JSR VFSCAN ;Scan for the name (heap is not used)
MOVEA.L 4(A5),A6 ;Get the address of the info array
MOVE.L BLKNO,(A6) ;Put the start and end blocks into it
MOVE.L ENDBLK,4(A6)
RTS
;-----------------------------------------------------------------------
;25
;Set the RERUN flag
; SETRUN('TRUE')
;
SETRUN MOVE.B #FALSE,RERUNF ;Assume it is false (=0)
TST.L (A5)
BEQ.S SR90
ST RERUNF ;Set it true if any bit was set
SR90 RTS
;-----------------------------------------------------------------------
;26
;Get a hex ASCII string from device DEV, convert it to a binary word,
; and return it in D0.
; I:= HEXIN(DEV)
;
HEXIN MOVE.B 3(A5),DEVICE ;Get the device number
BRA HEXI ;(PBRA) get the hex integer in D0
;-----------------------------------------------------------------------
;27
;Convert a 32-bit integer to an unsigned, hex ASCII string and send it
; out to device DEV.
; HEXOUT(DEV,I)
;
HEXOUT MOVE.B 3(A5),DEVICE ;Get the device number
MOVE.L 4(A5),D0 ;Get the integer
BRA HEXO ;(PBRA) output the hex integer
;-----------------------------------------------------------------------
;28
;Run a .SAV file
; CHAIN(UNIT, BLKNO)
;
CHAIN MOVE.B 3(A5),UNIT ;Get the arguments
MOVE.L 4(A5),BLKNO
JMP VFRUN ;Go run it (never returns)
;-----------------------------------------------------------------------
;29
;Open a disk file for input
; OPENF(UNIT, INFO);
; UNIT - unit number (0-7)
; INFO - the address of a 2-integer array containing the starting
; and ending blocks (usually gotten from SCAN)
;
OPENF MOVE.B 3(A5),INUNT ;Set the input unit
MOVEA.L 4(A5),A6 ;Get the address of the array
MOVE.L (A6),INLBLK ;Set the starting block number
MOVE.L 4(A6),INHBLK ;Set the ending block number
MOVE.B #1,INFLG ;1 = SETUP
MOVE.B #3,DEVICE ;Open the disk file for input
MOVEA.W #0,A6 ;Set the function code = OPENI
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;30
;Write the memory at BUFFER to UNIT for SIZE many BLOCKS
; WRITE(UNIT, BLOCK, BUFFER, SIZE)
;
WRITE MOVE.B 3(A5),UNIT ;Get the arguments
MOVE.L 4(A5),BLKNO
MOVE.L 8(A5),FADDR
MOVE.L 12(A5),NBLKS
MOVEA.W #12,A6 ;Set "write" function code
JMP VUNTHAN ;(PJMP) perform the unit function code
;-----------------------------------------------------------------------
;31
;Read into the memory at BUFFER FROM UNIT for SIZE many BLOCKS
; READ(UNIT, BLOCK, BUFFER, SIZE)
;
READ MOVE.B 3(A5),UNIT ;Get the arguments
MOVE.L 4(A5),BLKNO
MOVE.L 8(A5),FADDR
MOVE.L 12(A5),NBLKS
MOVEA.W #8,A6 ;Set "read" function code
JMP VUNTHAN ;(PJMP) perform the unit function code
;-----------------------------------------------------------------------
;32
;MODE:=TESTPT(X, Y)
TESTPT RTS
;======================================================================
;Special intrinsics for Apex
;-----------------------------------------------------------------------
;33
;Load a memory image and enter the monitor
; FGET(UNIT,BLKNO)
;
FGET MOVE.B 3(A5),UNIT ;Get arguments
MOVE.L 4(A5),BLKNO
JMP VFGET ;(Never returns)
;-----------------------------------------------------------------------
;34
;Write APEX.XPL to SYSTEM.SYS
; FASAVE(UNIT,BLKNO)
;
;FASAVE MOVE.B 3(A5),UNIT ;Get arguments
; MOVE.L 4(A5),BLKNO
; JMP VFASAVE ;(Never returns)
;
;-----------------------------------------------------------------------
;35
;Write a memory image for a .SAV file
; FSAVE(UNIT,BLKNO)
;
FSAVE MOVE.B 3(A5),UNIT ;Get arguments
MOVE.L 4(A5),BLKNO
JMP VFSAVE ;(Never returns)
;-----------------------------------------------------------------------
;36
;Routine to quickly move a block of memory.
; Move LEN many bytes from FROM to TO
; BLIT(TO, FROM, LEN)
;
BLIT MOVEM.L D1/A0,-(SP) ;Save register(s)
;Get arguments:
MOVEA.L (A5),A6 ; TO
MOVEA.L 4(A5),A0 ; FROM
MOVE.L 8(A5),D0 ; LEN
MOVE.L D0,D1 ;Put the high 16 bits of LEN into
SWAP D1 ; a second counter, D1
CMPA.L A0,A6 ;If TO > FROM (i.e: moving forward in
BEQ.S BLIT90 ; memory) then don't branch
BLO.S BLIT20 ;Enter loop checking for LEN = 0
ADDA.L D0,A6 ;Move starting at the end of the block
ADDA.L D0,A0 ;Add LEN to TO and FROM
BRA.S BLIT40 ;Enter loop checking for LEN = 0
BLIT10 MOVE.B (A0)+,(A6)+ ;Move block backward, pointers forward
BLIT20 DBF D0,BLIT10 ;Loop unitl D0 = -1
DBF D1,BLIT10 ; and also D1 = -1
BRA.S BLIT90 ;Exit
BLIT30 MOVE.B -(A0),-(A6) ;Move block forward, pointers backward
BLIT40 DBF D0,BLIT30 ;Loop unitl D0 = -1
DBF D1,BLIT30 ; and also D1 = -1
BLIT90 MOVEM.L (SP)+,D1/A0 ;Restore register(s)
RTS
;;======================================================================
;;33
;SETTXT RTS
;;
;;34
;SETHI RTS
;;
;;35
;SETMIX RTS
;;
;;36
;SETLO RTS
;-----------------------------------------------------------------------
;37
;BOOLEAN:=BUTTON(NUMBER)
BUTTON RTS
;
;38
;VARIALBE:=PADDLE(NUMBER)
PADDLE RTS
;39
;SOUND(VOLUME, CYCLES, PERIOD);
SOUND RTS
;40
CLEAR RTS
;41
;POINT(X, Y, MODE)
POINT RTS
;42
;LINE(X, Y, MODE)
LINE RTS
;43
;MOVE(X, Y)
MOVE RTS
;44
;VARIABLE:=SCREEN(X, Y)
SCREEN RTS
;45
;BLOCK(X, Y, COLOR)
BLOCK RTS
;======================================================================
;FLOATING POINT ROUTINES:
;-----------------------------------------------------------------------
;46
;Reserve heap space for a real array
; A5:= A5 + ARG *RLSIZE
; ADDR:= RLRES(REALS)
; The starting (low) address of the reserved space in returned in FP0.
;WARNING: This assumes that the heap and the stack are arranged so that
; they grow toward each other. This also assumes 8 bytes in a real.
;
RLRES MOVE.L A5,D0 ;Return the base address in FP0
DC.W $F200, $4000 ;FMOVE.L D0,FP0 (FLOAT)
MOVE.L (A5),D0 ;Get the number of reals to reserve
LSL.L #3,D0 ;Times 8 to get the number of bytes
ADDA.L D0,A5 ;Add the argument number of bytes
; to the heap pointer (A5)
CMPA.L SP,A5 ;Check for memory overflow
BLO.S RRES90
JSR VERROR
ASCII '103 - MEMORY OVERFLO'
DC.B 'W'+$80
RRES90 RTS
;-----------------------------------------------------------------------
;47
; X:= RLIN(DEV);
;
RLIN BRA BADINT
;-----------------------------------------------------------------------
;48
; RLOUT(DEV,X);
;
RLOUT BRA BADINT
;-----------------------------------------------------------------------
;49
;X:= FLOAT(I);
;(FMOVE.L -8(SP),FP0 is not implemented in FPP.68K)
;
FLOAT MOVE.L (A5),D0
DC.W $F200, $4000 ;FMOVE.L D0,FP0
RTS
;-----------------------------------------------------------------------
;50
;I:= FIX(X);
;
FIX DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $6000 ;FMOVE.L FP0,D0
RTS
;-----------------------------------------------------------------------
;51
;X:= RLABS(X);
;
RLABS DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $0018 ;FABS.X FP0
RTS
;-----------------------------------------------------------------------
;52
;FORMAT(M,N);
;
FORMAT BRA.L BADINT
;-----------------------------------------------------------------------
;53
;X:= SQRT(X);
;(FSQRT.D (A5),FP0 et cetra are not implemented in FPP.68K)
;
SQRT DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $0004 ;FSQRT.X FP0
RTS
;-----------------------------------------------------------------------
;54
;X:= LN(X);
;
LN DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $0014 ;FLOGN.X FP0
RTS
;-----------------------------------------------------------------------
;55
;X:= EXP(X);
;
EXP DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $0010 ;FETOX.X FP0
RTS
;-----------------------------------------------------------------------
;56
;X:= SIN(X);
;
SIN DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $000E ;FSIN.X FP0
RTS
;-----------------------------------------------------------------------
;57
;X:= ATAN2(Y,X);
;
ATAN2 BRA.L BADINT
;-----------------------------------------------------------------------
;58
;X:= MOD(A,B);
;
MOD BRA.L BADINT
;-----------------------------------------------------------------------
;59
;X:= LOG(X);
;
LOG DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $0015 ;FLOG10.X FP0
RTS
;-----------------------------------------------------------------------
;60
;X:= COS(X);
;
COS DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $001D ;FCOS.X FP0
RTS
;-----------------------------------------------------------------------
;61
;X:= TAN(X);
;
TAN DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $000F ;FTAN.X FP0
RTS
;-----------------------------------------------------------------------
;62
;X:= ASIN(X);
;
ASIN DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $000C ;FACOS.X FP0
RTS
;-----------------------------------------------------------------------
;63
;X:= ACOS(X);
;
ACOS DC.W $F215, $5400 ;FMOVE.D (A5),FP0
DC.W $F200, $001C ;FACOS.X FP0
RTS
;-----------------------------------------------------------------------
;64
;Set the backup flag, so the next CHIN will reread the same byte.
;BACKUP
;
BACKUP ST BACKFL ;Set on condition true, i.e. always
RTS
;======================================================================
;-----------------------------------------------------------------------
;65
;HICHAR(X, Y, MODE, ROT, CHAR)
;
HICHAR RTS
;-----------------------------------------------------------------------
;66
;Return the value of the byte in the Apple at the given address
;BYTE:=PEEK(ADDRESS)
;
PEEK RTS
;-----------------------------------------------------------------------
;67
;Store the byte in the Apple at the given address
;POKE(ADDR,BYTE)
;
POKE RTS
;======================================================================
;----------------------------------------------------------------------
;119
;Move cursor on the second terminal (device #1) to column X, line Y.
; Upper left corner is X,Y = 0,0.
; CURSOR1(X,Y)
; A6 is destroyed.
;
CURSOR1 MOVE.B #1,DEVICE ;Set to device number 1
MOVE.B 3(A5),D0 ;Get X position
ROL.W #8,D0 ;Put it into high byte of D0
MOVE.B 7(A5),D0 ;Get Y position into low byte
MOVEA.W #28,A6 ;Set function code = "position cursor"
JMP VDEVHAN ;(PJMP) do I/O
;-----------------------------------------------------------------------
;120
;Set the display attributes for the second terminal (device #1)
; BUTES1($1);
;The bits in the argument set the attributes as follows:
; 0 - bold (not dim)
; 1 - underline
; 2 - inverse video
; 3 - flashing
;
;WARNING: The Wyse terminal is severely brain-damaged, and it insists on
; inserting a space character whenever attributes are changed.
;
BUTES1 MOVE.L (A5),D0 ;Get argument
MOVE.B #1,DEVICE ;Set to device # 1
MOVEA.W #48,A6 ;Set function code for "butes"
JMP VDEVHAN ;(PJMP) go do it
;-----------------------------------------------------------------------
;121
;Turn the cursor indicator on or off for the second terminal (device #1)
; SHOCUR1('TRUE');
;
SHOCUR1 MOVE.L (A5),D0 ;Get boolean argument
MOVE.B #1,DEVICE ;Set to device # 1
MOVEA.W #44,A6 ;Set function code for cursor control
JMP VDEVHAN ;(PJMP) go do it
;-----------------------------------------------------------------------
;122
;Return the address of the information array for a device
; ADDR:= DEVINFO(DEV)
;
DEVINFO MOVE.B 3(A5),DEVICE ;Get the device number
MOVEA.W #20,A6 ;Set function code for "getinfo"
JMP VDEVHAN ;(PJMP) go do it
;-----------------------------------------------------------------------
;123
;Return the address of the information array for a unit
; ADDR:= UNTINFO(UNIT)
;
UNTINFO MOVE.B 3(A5),UNIT ;Get the unit number
MOVEA.W #20,A6 ;Set function code for "getinfo"
JMP VUNTHAN ;(PJMP) go do it
;-----------------------------------------------------------------------
;124
;Set the display attributes for device 0
; BUTES($1);
;The bits in the argument set the attributes as follows:
; 0 - bold (not dim)
; 1 - underline
; 2 - inverse video
; 3 - flashing
;
;WARNING: The Wyse terminal is severely brain-damaged, and it insists on
; inserting a space character whenever attributes are changed.
;
BUTES MOVE.L (A5),D0 ;Get argument
MOVE.B #0,DEVICE ;Set to device # 0
MOVEA.W #48,A6 ;Set function code for "butes"
JMP VDEVHAN ;(PJMP) go do it
;-----------------------------------------------------------------------
;125
;Wait for and then return the value of a key struck on
; the keyboard
; I:= GETKEY;
;
GETKEY MOVE.B #1,DEVICE ;Set to device # 1
MOVEA.W #36,A6 ;Set function code for "getkey"
JMP VDEVHAN ;(PJMP) return with value in D0
;-----------------------------------------------------------------------
;126
;Determine if a key (on the keyboard) has been struck
; I:= KEYHIT;
;
KEYHIT MOVE.B #1,DEVICE ;Set to device # 1
MOVEA.W #40,A6 ;Set function code
JMP VDEVHAN ;(PJMP) return with boolean in D0
;-----------------------------------------------------------------------
;127
;Turn the cursor indicator on or off for device 0
; SHOCUR('TRUE');
;
SHOCUR MOVE.L (A5),D0 ;Get boolean argument
MOVE.B #0,DEVICE ;Set to device # 0
MOVEA.W #44,A6 ;Set function code for cursor control
JMP VDEVHAN ;(PJMP) go do it
;=======================================================================
;SUBROUTINES:
;-----------------------------------------------------------------------
;Input ASCII digits and convert them to a signed, decimal, 32-bit value
; which is returned in D0.
; D0 = I/O
; D1 = Working register (contains number to be converted)
; D2 = Flag: a numeric character has been entered
; D3 = 10 multiplier
; D4 = Flag: a minus sign was entered, i.e. the number is negative
;
INTI MOVEM.L D1-D4,-(SP) ;Save registers
II00 MOVEQ #0,D1 ;NUM:=0;
CLR.B D2 ;NUMFLG:=false
CLR.B D4 ;SIGN:=false
MOVEQ #10,D3
BSR BYTEIN ;Get byte
CMPI.B #'-',D0 ;if D0 = ^- then SIGN := true
BNE.S II30
MOVEQ #TRUE,D4
; ;loop begin
II20 BSR BYTEIN ;Get byte
II30 CMPI.B #'0',D0 ; if D0<^0 ! D0>^9 then quit
BLO.S II50
CMPI.B #'9',D0
BHI.S II50
MOVEQ #TRUE,D2 ; NUMFLG:=true
MOVE.L D1,D3 ; NUM:= NUM*10 + (D0-^0)
LSL.L #2,D1 ; *4
ADD.L D3,D1 ; +1
LSL.L #1,D1 ; *2
SUBI.B #'0',D0
ADD.L D0,D1
BRA.S II20 ; end
II50 TST.B D2 ;if NUMFLG then quit
BEQ.S II00
TST.B D4 ;if SIGN then NUM:= -NUM
BEQ.S II60
NEG.L D1
II60 MOVE.L D1,D0 ;return NUM
MOVEM.L (SP)+,D1-D4 ;Restore registers
RTS
;-----------------------------------------------------------------------
;Convert the signed, 32-bit value in D0 to decimal ASCII and output the
; characters to DEVICE.
; D0 = I/O and subtract counter
; D1 = Working register (contains number to be converted)
; D2 = Flag used to suppress leading zeros (suppress if false)
; D3 = Power-of-ten (loop) counter
; D4 = Power of ten
; A0 = Pointer to power-of-ten table
;
INTO MOVEM.L D0-D4/A0/A6,-(SP) ;Save registers
MOVEA.W #12,A6 ;Set the function code = CHOUT
MOVE.L D0,D1 ;Put number into the working register
BPL.S INTO10 ;Branch if it is positive
NEG.L D1 ;Otherwise make it positive
MOVEQ #'-',D0 ;Output the minus sign
JSR VDEVHAN ;Output D0
;Initialize:
INTO10 MOVEQ #FALSE,D2 ; flag used to suppress leading zeros
MOVEQ #8,D3 ; loop counter (8 down through 0)
LEA TENTBL.L,A0 ; pointer to power-of-ten table
INTO20 MOVE.L (A0)+,D4 ;Get a power of ten
MOVEQ #9,D0 ;Init loop counter (9-0)
INTO30 SUB.L D4,D1 ;Repeatedly subtract a power of ten
DBMI D0,INTO30 ; until it goes negative
ADD.L D4,D1 ;Restore to positive value
NEG.B D0 ;This digit = 9 - D0
ADD.B #9,D0
BNE.S INTO40 ;Branch if digit is not zero
TST.B D2 ;Are we suppressing leading zeros?
BEQ.S INTO50 ;Branch if we are (i.e. flag = false)
INTO40 MOVEQ #TRUE,D2 ;Turn leading zero suppression off
ADD.B #'0',D0 ;Convert digit to ASCII
JSR VDEVHAN ;Output it
INTO50 DBF D3,INTO20 ;Repeat for powers 1,000,000,000 down
; thru 10;
MOVE.B D1,D0 ;Output the one's digit regardless of
ADD.B #'0',D0 ; the leading zero suppression flag
JSR VDEVHAN
MOVEM.L (SP)+,D0-D4/A0/A6 ;Restore registers
RTS
;Power-of-ten table:
TENTBL DC.L 1000000000 ;1g
DC.L 100000000
DC.L 10000000
DC.L 1000000 ;1m
DC.L 100000
DC.L 10000
DC.L 1000 ;1k
DC.L 100
DC.L 10
;-----------------------------------------------------------------------
;Output a text string pointed to by A6.
; The string is terminated with a character having its MSB set.
;
TEXTO MOVEM.L A0/A6,-(SP) ;Save registers
MOVEA.L A6,A0 ;Get string address
MOVEA.W #12,A6 ;Set the function code to CHOUT
BRA.S TXT20 ;Enter loop
TXT10 JSR VDEVHAN ;Output D0
TXT20 MOVE.B (A0)+,D0 ;Get char from string
BPL.S TXT10 ;Loop unitl the last character
ANDI.B #$7F,D0 ;Clear MSB
JSR VDEVHAN ;Output D0
MOVEM.L (SP)+,A0/A6 ;Restore registers
RTS
;-----------------------------------------------------------------------
;Input hex ASCII digits from DEVICE and convert them to a 32-bit value
; which is returned in D0.
; D0 = Digit
; D1 = Accumulated value
; D2 = Digit counter
;
HEXI MOVEM.L D1-D2,-(SP) ;Save registers
MOVEQ #0,D1 ;Clear result register
MOVEQ #7,D2 ;Init digit counter (7 down through 0)
HEXI00 BSR BYTEIN ;Get byte
CMPI.B #'0',D0 ;Is character in range 0 thru 9?
BLO.S HEXI40 ;Branch if not
CMPI.B #'9',D0
BHI.S HEXI20 ;(May be A-F)
SUBI.B #'0',D0 ;Convert ASCII to binary value
BRA.S HEXI30 ;Go combine with other digits
HEXI20 ANDI.B #$DF,D0 ;Force to uppercase
CMPI.B #'A',D0 ;Is character in range A thru F?
BLO.S HEXI40 ;Branch if not
CMPI.B #'F',D0
BHI.S HEXI40
SUBI.B #'A'-10,D0 ;Convert ASCII to binary value
HEXI30 ASL.L #4,D1 ;Multiply current value by 16
ADD.B D0,D1 ;Add new digit
DBF D2,HEXI00 ;Exit if we have 8 digits
HEXI40 CMPI.B #7,D2 ;Did we find a valid hex digit?
BEQ.S HEXI00 ;Branch if not -- keep trying
MOVE.L D1,D0 ;Return the hex value in D0
MOVEM.L (SP)+,D1-D2 ;Restore registers
RTS
;-----------------------------------------------------------------------
;Output D0 in ASCII hex (8 digits)
;
HEXO SWAP D0 ;Get high word
BSR.S WRDOUT ;Output it
SWAP D0 ;(PFALL) get low word back
;-----------------------------------------------------------------------
;Output D0 in ASCII hex (4 digits)
;
WRDOUT ROR.W #8,D0 ;Move high byte down (and save low byte)
BSR.S BYTOUT ;Output it
ROR.W #8,D0 ;(PFALL) get low byte
;-----------------------------------------------------------------------
;Output D0 in ASCII hex (2 digits)
;
BYTOUT ROR.B #4,D0 ;Move high nybble down (save low nybble)
BSR.S NYBOUT ;Output it
ROR.B #4,D0 ;(PFALL) get low nybble
;-----------------------------------------------------------------------
;Output D0 in ASCII hex (1 digit)
;
NYBOUT MOVEM.L D0/A6,-(SP) ;Save registers
ANDI.B #$0F,D0 ;Work with low nybble only
CMPI.B #10,D0
BLO.S NO10
ADDQ.B #7,D0
NO10 ADDI.B #'0',D0 ;Convert to ASCII
MOVEA.W #12,A6 ;Set the function code = CHOUT
JSR VDEVHAN ;Output D0
MOVEM.L (SP)+,D0/A6 ;Restore registers
RTS
;-----------------------------------------------------------------------
;Input a byte from DEVICE and return it in D0.
;
BYTEIN TST.B BACKFL ;Re-read the last character?
BEQ.S BYIN20 ;Branch if not
CLR.B BACKFL ;Clear backup flag
MOVEQ #0,D0
MOVE.B LASTCH,D0 ;Return the last character
RTS
BYIN20 MOVE.L A6,-(SP) ;Save A6
MOVEA.W #8,A6 ;Set the function code = CHIN
JSR VDEVHAN ;Do I/O
MOVE.B D0,LASTCH ;Save in case we need to re-read it
MOVEA.L (SP)+,A6 ;Restore A6
RTS
IF @ > MEMTOP - $3000
ERROR -- TOO BIG
ENDIF
END
in case we need to re-read it
MOVEA